package zhh.tangbao.wechat.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import zhh.tangbao.auxiliary.entity.SystemOpinion;
import zhh.tangbao.auxiliary.service.SystemOpinionService;
import zhh.tangbao.auxiliary.vo.opinion.OpinionInfoVo;
import zhh.tangbao.auxiliary.vo.opinion.OpinionTypeSelectOptionVo;
import zhh.tangbao.commodity.entity.CommodityMachineHistory;
import zhh.tangbao.commodity.entity.CommodityOrder;
import zhh.tangbao.commodity.serivce.CommodityOrderService;
import zhh.tangbao.syslog.entity.WorkRecord;
import zhh.tangbao.system.annotation.WeChatTokenAccess;
import zhh.tangbao.system.entity.PagerEntity;
import zhh.tangbao.system.exception.ServiceException;
import zhh.tangbao.system.result.Result;
import zhh.tangbao.system.utils.ConvertUtils;
import zhh.tangbao.wechat.dto.WeChatMachineQueryDto;
import zhh.tangbao.wechat.dto.WeChatOrderQueryDto;
import zhh.tangbao.wechat.dto.WeChatUserLoginDto;
import zhh.tangbao.wechat.dto.commodity.CommodityQueryDto;
import zhh.tangbao.wechat.dto.opinion.UserOpinionQueryDto;
import zhh.tangbao.wechat.dto.replenishment.ReplenishmentMachineStockQueryDto;
import zhh.tangbao.wechat.dto.replenishment.ReplenishmentStockDataDto;
import zhh.tangbao.wechat.dto.worker.WorkerRecordQueryDto;
import zhh.tangbao.wechat.entity.WeChatUser;
import zhh.tangbao.wechat.pojo.CartItem;
import zhh.tangbao.wechat.service.WeChatService;
import zhh.tangbao.wechat.vo.cart.CartItemVo;
import zhh.tangbao.wechat.vo.commodity.CommodityPageInMachineVo;
import zhh.tangbao.wechat.vo.opinion.UserOpinionListItemVo;
import zhh.tangbao.wechat.vo.order.OrderDetailVo;
import zhh.tangbao.wechat.vo.replenishment.ReplenishmentMachineStockVo;
import zhh.tangbao.wechat.vo.worker.WorkerPanel;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;


/**
 * 2023/2/27
 *
 * @author 粥灰灰
 * @version 1.0
 * 微信服务
 */

@Slf4j
@RestController
@RequestMapping("/api/wechat")
public class WeChatController {

    @Autowired
    private WeChatService service;

    @Autowired
    private SystemOpinionService opinionService;


    /**
     * 授权登录接口
     * 当小程序用户第一次或者重新需要登录小程序的时候调用此接口进行登录业务
     * 登录前需要用户同意小程序的授权
     */
    @PostMapping("/login")
    @WeChatTokenAccess(login = false)
    public Result login(@RequestBody WeChatUserLoginDto dto) {
        return Result.success().put(service.login(dto));
    }

    /**
     * 快捷登录接口
     * 小程序用户登录过后，小程序中会储存token缓存
     * 此接口使用token进行用户上线，并验证当前用户token是否过期
     * 当token过期时需要让用户走一遍login流程
     */
    @GetMapping("/quickLogin")
    @WeChatTokenAccess(login = false)
    public Result quickLogin(String token) {
        WeChatUser weChatUser = service.getWeChatUserByToken(token);
        // 如果过期则告诉用户需要重新登录
        if (service.updateIfNotExpire(weChatUser)) {
            return Result.needReEntry("登录授权过期，请重新登录");
        }
        weChatUser.setOpenId(null);
        return Result.success().put(weChatUser);
    }

    @GetMapping("/logout")
    @WeChatTokenAccess
    public Result logout() {
        service.logout();
        return Result.success();
    }

    /**
     * 采用懒加载分页形式展示
     * 老式分页，从pageNum0开始计数
     */
    @GetMapping("/order")
    @WeChatTokenAccess
    public Result order(WeChatOrderQueryDto dto) {
        return Result.success().put(service.wechatPage(dto));
    }

    /**
     * 查询当前条件下订单的总个数
     * 当懒加载数据数量等于总个数时无需再次获取数据
     * 单独分割该接口是为了减少调用查询总数SQL的次数
     */
    @GetMapping("/orderCount")
    @WeChatTokenAccess
    public Result orderCount(WeChatOrderQueryDto dto) {
        return Result.success().put(service.wechatOrderCount(dto));
    }

    @GetMapping("/delete/{id}")
    @WeChatTokenAccess
    public Result orderCount(@PathVariable("id") String id) {
        return Result.success().put(service.wechatDeleteOrder(id));
    }

    /**
     * 老式分页，从pageNum0开始计数
     */
    @GetMapping("/machineList")
    public Result machineList(WeChatMachineQueryDto dto) {
        return Result.success().put(service.machinePage(dto));
    }

    @GetMapping("/machineCount")
    public Result machineCount(WeChatMachineQueryDto dto) {
        return Result.success().put(service.machineCount(dto));
    }

    /**
     * 用户售货机浏览记录列表
     */
    @GetMapping("/userMachineHistoryPage")
    @WeChatTokenAccess
    public Result userMachineHistoryPage(WeChatMachineQueryDto dto) {
        return Result.success().put(service.userMachineHistoryPage(dto));
    }

    /**
     * 用户售货机浏览记录总数
     * 用总数和当前列表长度进行比较，如果总数 == 长度代表列表展示完毕
     */
    @GetMapping("/userMachineHistoryCount")
    @WeChatTokenAccess
    public Result userMachineHistoryCount(WeChatMachineQueryDto dto) {
        return Result.success().put(service.userMachineHistoryCount(dto));
    }

    /**
     * 在用户成功进入售货机界面的时候调用
     * 增加或更新用户的浏览记录
     * 如果从历史记录进入界面会带有机器历史记录id
     */
    @PostMapping("/upsertHistory")
    @WeChatTokenAccess
    public Result upsertHistory(@RequestBody CommodityMachineHistory history) {
        return Result.successOrFail(service.upsertMachineHistory(history));
    }

    /**
     * 提交订单，并且设置订单付款容错期限
     * 如果对方取消付款的话仍有一段时间可以付款
     * @return 订单号
     */
    @PostMapping("/buy")
    @WeChatTokenAccess
    public Result buy(@RequestBody CommodityOrder order) {
        return Result.success().put(service.buy(order));
    }

    @GetMapping("/requestPayment")
    @WeChatTokenAccess
    public Result requestPayment(String orderId) {
        Map<String, String> result = service.requestPayment(orderId);
        return Result.success().put(result);
    }

    /**
     * 获取用户取货凭证
     */
    @GetMapping("/getReceipt")
    @WeChatTokenAccess
    public Result getReceipt(String orderId) {
        return Result.success().put(service.getReceipt(orderId));
    }


    /**
     * 微信支付回调接口
     */
    @RequestMapping("/orderPaymentReCall")
    public String orderPaymentReCall(HttpServletRequest request) {
        Map<String, String> result = Maps.newHashMap();
        try (
                ServletInputStream inputStream = request.getInputStream();
        ) {
            Map<String, String> map = ConvertUtils.XMLParsing(inputStream);
            // 支付成功，更新订单更新时间
            if (!"SUCCESS".equals(map.get("return_code"))) {
                throw new ServiceException(map.get("return_msg"));
            }
            String orderId = map.get("out_trade_no");
            service.orderPayment(orderId);
            result.put("return_code", "SUCCESS");
            result.put("return_msg", "SUCCESS");
        } catch (IOException | DocumentException e) {
            log.error("zhh.tangbao.wechat.controller.WeChatController.orderPaymentReCall: {}", e.getMessage());
            result.put("return_code", "FAIL");
            result.put("return_msg", "ERROR");
        }
        return ConvertUtils.mapToXmlString(result);
    }

    /**
     * 在订单还未付款之前用户可以主动取消订单
     */
    @GetMapping("/cancelOrder")
    @WeChatTokenAccess
    public Result cancelOrder(String orderId) {
        return Result.successOrFail(service.cancelOrder(orderId));
    }

    @GetMapping("/waitCount")
    public Result waitCount(String machineId, String orderId) {
        return Result.success().put(service.waitCount(machineId, orderId));
    }


    @GetMapping("/commodityPageInMachine")
    public Result commodityPageInMachine(PagerEntity<CommodityPageInMachineVo> pager, CommodityQueryDto dto) {
        PagerEntity<CommodityPageInMachineVo> page = service.commodityPageInMachine(pager, dto);
        return Result.success().put(page);
    }

    @GetMapping("/getPhoneNumber")
    @WeChatTokenAccess
    public Result getPhoneNumber(String getPhoneCode) {
        String phoneNumber = service.getPhoneNumber(getPhoneCode);
        return Result.success().put(phoneNumber);
    }

    @PostMapping("/addUserCart")
    @WeChatTokenAccess
    public Result addUserCart(@RequestBody CartItem item) {
        service.addUserCart(item);
        return Result.success();
    }

    /**
     * 获取当前登录用户的购物车清单
     */
    @GetMapping("/getUserCartList")
    @WeChatTokenAccess
    public Result getUserCartList() {
        List<CartItemVo> cartItemVos = service.userCart();
        return Result.success().put(cartItemVos);
    }

    @DeleteMapping("/deleteUserCart/{stockIndex}/{stockId}")
    @WeChatTokenAccess
    public Result deleteUserCart(@PathVariable("stockIndex") Integer stockIndex,@PathVariable("stockId") Integer stockId) {
        return Result.successOrFail(service.deleteUserCart(stockIndex,stockId));
    }

    @GetMapping("/orderDetail/{id}")
    public Result orderDetail(@PathVariable("id") String id) {
        OrderDetailVo vo = service.getWeChatOrderDetail(id);
        return Result.success().put(vo);
    }

    /** 员工面板数据 */
    @GetMapping("/workerPanel")
    @WeChatTokenAccess
    public Result workerPanel() {
        WorkerPanel w = service.getWorkerPanel();
        return Result.success().put(w);
    }

    @GetMapping("/workerRecordList")
    @WeChatTokenAccess
    public Result workerRecordList(WorkerRecordQueryDto dto) {
        Page<WorkRecord> result = service.getWorkerRecordList(dto);
        return Result.success().put(result);
    }

    @PostMapping("/submitRecord")
    @WeChatTokenAccess
    public Result submitRecord(@RequestBody WorkRecord record) {
        return Result.successOrFail(service.submitRecord(record));
    }

    /**
     * 老式分页
     * 页码从0开始
     * @param dto
     * @return
     */
    @GetMapping("/replenishmentMachineStock")
    @WeChatTokenAccess(replenishment = true)
    public Result machineStock(PagerEntity<ReplenishmentMachineStockVo> pager, ReplenishmentMachineStockQueryDto dto) {
        return Result.success().put(service.machineStockPager(pager, dto));
    }

    @PostMapping("/replenishmentStock")
    @WeChatTokenAccess(replenishment = true)
    public Result replenishmentMachineStockData (@RequestBody ReplenishmentStockDataDto dto) {
        return Result.successOrFail(service.replenishmentMachineStockData(dto));
    }

    @GetMapping("/userOpinionPage")
    @WeChatTokenAccess
    public Result getUserOpinionPage(UserOpinionQueryDto dto) {
        Page<UserOpinionListItemVo> page = service.getUserOpinionPage(dto);
        return Result.success().put(page);
    }

    @GetMapping("/userOpinionDetail")
    public Result getUserOpinionDetail(String id) {
        OpinionInfoVo vo = service.getUserOpinionDetail(id);
        return Result.success().put(vo);
    }

    @GetMapping("/opinionType")
    public Result opinionType() {
        List<OpinionTypeSelectOptionVo> vos = opinionService.opinionType();
        return Result.success().put(vos);
    }

    @PostMapping("/submitOpinion")
    @WeChatTokenAccess
    public Result submitOpinion(@RequestBody SystemOpinion opinion) {
        return Result.successOrFail(service.submitOpinion(opinion));
    }
}
